package spring.cloud.tasks.executor.listener.failover;

import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import spring.cloud.tasks.executor.listener.TreeCacheListener;
import spring.cloud.tasks.executor.node.TaskNodePaths;
import spring.cloud.tasks.executor.task.ExecuteNode;
import spring.cloud.tasks.executor.utils.log.LogUtils;

@Slf4j
@Setter
@Getter
class ExecutionListener extends TreeCacheListener {

    private final FailoverListenerHolder failoverListener;

    public ExecutionListener(FailoverListenerHolder failoverListener) {
        this.failoverListener = failoverListener;
    }

    @Override
    protected void dataChanged(CuratorFramework curatorFramework, String path, TreeCacheEvent treeCacheEvent) {
        try {
            if (failoverListener.isShutdown) {
                return;
            }
            if (failoverListener.executionPath.equals(path)) {
                return;
            }
            int item = getItem(path);
            String runningPath = TaskNodePaths.getTaskNodePath(failoverListener.taskId, ExecuteNode.getRunningNode(item));
            String failoverPath = TaskNodePaths.getTaskNodePath(failoverListener.taskId, FailoverNode.getExecutionFailoverNode(item));
            switch (treeCacheEvent.getType()) {
                case NODE_ADDED:
                    failoverListener.nodeCacheOrTreeCacheManager.addNodeCacheListener(runningPath, new RunningPathListener(failoverListener, item));
                    failoverListener.runningAndFailoverPath.add(runningPath);
                    failoverListener.nodeCacheOrTreeCacheManager.addNodeCacheListener(failoverPath, new FailoverPathListener(failoverListener, item));
                    failoverListener.runningAndFailoverPath.add(failoverPath);
                    break;
                case NODE_REMOVED:
                    failoverListener.nodeCacheOrTreeCacheManager.closeNodeCache(runningPath);
                    failoverListener.runningAndFailoverPath.remove(runningPath);
                    failoverListener.nodeCacheOrTreeCacheManager.closeNodeCache(failoverPath);
                    failoverListener.runningAndFailoverPath.remove(failoverPath);
                    break;
                default:
            }
        } catch (Exception e) {
            LogUtils.error(log, failoverListener.taskId, e.getMessage(), e);
        }
    }

    private int getItem(String path) {
        return Integer.parseInt(path.substring(path.lastIndexOf('/') + 1));
    }

}
